<template>
  <view class="container">
    <view class="header-title">
      <text class="header-title-tips">{{ titleTips }}</text>
    </view>

    <!-- 使用video元素显示摄像头画面 -->
    <view>
      <view v-if="isCameraStarting">摄像头启动中...</view>
      <video ref="video" autoplay playsinline :style="{ width: '100%', height: 'auto' }"></video>
    </view>

    <image style="width: 400rpx; height: 402rpx; position: absolute; left: 175rpx; top: 175rpx;"
      src="/static/face/circleBg.png" />

    <!-- 拍照按钮 -->
    <view class="start-button" :style="{ marginTop: '120rpx', flexDirection: 'row', justifyContent: 'center' }">
      <view class="button-hover"
        :style="{ width: '480rpx', padding: '24rpx', borderRadius: '300rpx', backgroundColor: 'rgba(12, 75, 158, 1)' }"
        @click="takePhoto">
        <text class="button-tip"
          :style="{ fontSize: '32rpx', color: '#dfdfdf', textAlign: 'center' }">{{ buttonTip }}</text>
      </view>
    </view>

    <!-- 显示拍照结果 -->
    <image v-if="photoData" :src="photoData" mode="widthFix" style="width: 100%; margin-top: 10px;" />

    <!-- 消息提示 -->
    <u-toast ref="uToast" />
  </view>
</template>

<script>
export default {
  data() {
    return {
      titleTips: "请把人脸放在圆圈内拍摄脸部，开始人脸识别",
      buttonTip: "开始人脸识别",
      photoData: "", // 存储拍照后的图片数据
      videoStream: null, // 存储视频流
      isCameraStarting: false // 防止重复调用
    };
  },
  methods: {
    // 处理摄像头错误
    handleCameraError(error) {
      console.error("摄像头错误：", error);
      let message = "无法访问摄像头，请检查权限";

      switch (error.name) {
        case 'NotAllowedError':
          message = "摄像头权限被拒绝，请前往设置允许访问";
          break;
        case 'NotFoundError':
          message = "未找到可用的摄像头";
          break;
        case 'NotReadableError':
          message = "摄像头被其他应用占用，请关闭后重试";
          break;
        case 'OverconstrainedError':
          message = "无法满足摄像头配置要求";
          break;
      }

      uni.$u.toast(message);
    },

    // 更可靠的权限检查
    async checkCameraPermission() {
      try {
        const devices = await navigator.mediaDevices.enumerateDevices();
        const videoDevices = devices.filter(device => device.kind === 'videoinput');

        if (videoDevices.length === 0) {
          uni.$u.toast("未检测到摄像头");
          return false;
        }

        // 检查是否有未授权的设备（deviceId为空）
        const hasUnauthorizedDevices = videoDevices.some(device =>
          device.deviceId === '' || !device.deviceId
        );

        if (hasUnauthorizedDevices) {
          return false; // 需要请求权限
        }

        return true; // 已有权限
      } catch (error) {
        console.error('权限检查错误:', error);
        return false;
      }
    },

    // 请求摄像头权限并启动
    async requestCameraPermission() {
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: {
            facingMode: "user",
            width: { ideal: 1280 },
            height: { ideal: 720 }
          },
        });
        await this.startVideoStream(stream);
        return true;
      } catch (error) {
        this.handleCameraError(error);
        return false;
      }
    },

    // 启动摄像头（主入口）
    async startCamera() {
      // 防止重复调用
      if (this.isCameraStarting) {
        return;
      }

      this.isCameraStarting = true;

      try {
        // 先停止已有的流
        if (this.videoStream) {
          this.stopCamera();
        }

        const hasPermission = await this.checkCameraPermission();

        if (!hasPermission) {
          await this.requestCameraPermission();
        } else {
          // 已经有权限，直接获取流
          const stream = await navigator.mediaDevices.getUserMedia({
            video: {
              facingMode: "user",
              width: { ideal: 1280 },
              height: { ideal: 720 }
            },
          });
          await this.startVideoStream(stream);
        }
      } catch (error) {
        this.handleCameraError(error);
      } finally {
        this.isCameraStarting = false;
      }
    },

    // 改进的视频流启动方法
    async startVideoStream(stream) {
      return new Promise((resolve, reject) => {
        const videoElement = this.$refs.video;

        if (!videoElement) {
          reject(new Error('Video element not found'));
          return;
        }

        // 先设置srcObject
        videoElement.srcObject = stream;
        this.videoStream = stream;

        // 等待视频元素准备就绪（iOS关键步骤）
        const onLoadedMetadata = () => {
          videoElement.removeEventListener('loadedmetadata', onLoadedMetadata);

          // 尝试播放视频
          videoElement.play()
            .then(() => {
              console.log('摄像头启动成功');
              resolve();
            })
            .catch(playError => {
              console.error('视频播放失败:', playError);
              reject(playError);
            });
        };

        const onError = () => {
          videoElement.removeEventListener('error', onError);
          reject(new Error('视频元素加载错误'));
        };

        videoElement.addEventListener('loadedmetadata', onLoadedMetadata);
        videoElement.addEventListener('error', onError);

        // 设置超时处理
        setTimeout(() => {
          videoElement.removeEventListener('loadedmetadata', onLoadedMetadata);
          videoElement.removeEventListener('error', onError);
          reject(new Error('视频加载超时'));
        }, 10000); // 10秒超时
      });
    },

    // 停止摄像头
    stopCamera() {
      if (this.videoStream) {
        this.videoStream.getTracks().forEach(track => {
          track.stop();
        });
        this.videoStream = null;
      }

      const videoElement = this.$refs.video;
      if (videoElement) {
        videoElement.srcObject = null;
      }
    },

    // 手动拍照
    takePhoto() {
      const video = this.$refs.video;
      if (video && video.videoWidth && video.videoHeight) {
        const canvas = document.createElement("canvas");
        const context = canvas.getContext("2d");
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        this.photoData = canvas.toDataURL("image/png"); // 获取拍照后的图片数据
      }
    },

    // 获取手机系统信息
    getPhoneSys() {
      const system = uni.getDeviceInfo();
      this.phoneSysInfos = system;
    },
  },
  mounted() {
    // 启动摄像头
    this.startCamera();
    this.getPhoneSys();
  },
  beforeDestroy() {
    // 释放视频流
    if (this.videoStream) {
      this.videoStream.getTracks().forEach(track => track.stop());
    }
  },
  // 页面生命周期处理
  onHide() {
    this.stopCamera();
  },

  onUnload() {
    this.stopCamera();
  }
};
</script>


<style lang="scss" scoped>
.header-title {
  margin: 20rpx;

  .header-title-tips {
    text-align: center;
    font-size: 32rpx;
    color: #666;
    margin-bottom: 76rpx;
  }
}

.start-button {
  margin-top: 120rpx;
  flex-direction: row;
  justify-content: center;
}

.button-hover {
  width: 480rpx;
  padding: 24rpx;
  border-radius: 300rpx;
  background-color: rgba(12, 75, 158, 1);
}

.button-tip {
  font-size: 32rpx;
  color: #dfdfdf;
  text-align: center;
}

.footer {
  margin-top: 50rpx;

  .footer-tips {
    text-align: center;
    font-size: 28rpx;
    color: #999;
  }

  .footer-required {
    margin-top: 100rpx;
    flex-direction: row;
    justify-content: space-around;
    padding: 0 50rpx;

    .row-area {
      text-align: center;

      .row-area-img-box {
        flex-direction: row;
        justify-content: center;

        .row-area-img {
          padding: 10rpx;
          background-color: skyblue;
          border-radius: 50%;
          width: 52rpx;
          height: 52rpx;
        }
      }

      .row-area-tip {
        margin-top: 14rpx;
        color: #666;
        font-size: 28rpx;
      }
    }
  }
}
</style>
